﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Lacrima.Framework.Infrastructure
{
    /// <summary>
    /// Mysql数据库帮助类
    /// </summary>
    public static class MySQLUtil
    {
        /// <summary>
        /// 创建插入数据库的SQL语句
        /// </summary>
        /// <typeparam name="TEntity">数据表对应数据库实体类</typeparam>
        /// <param name="entity">实体对象</param>
        /// <returns>插入SQL</returns>
        public static string CreateInsertSQL<TEntity>(this TEntity entity) where TEntity : class,new()
        {
            Type type = typeof(TEntity);
            StringBuilder sql = new StringBuilder(" INSERT INTO ");
            sql.Append("`");
            sql.Append(type.Name);
            sql.Append("`");
            sql.Append(CreateColumnString<TEntity>());
            sql.Append(" VALUES");
            sql.Append(CreateValueString(entity));
            return sql.ToString();
        }

        /// <summary>
        /// 创建插入数据库的SQL语句
        /// </summary>
        /// <typeparam name="TEntity">数据表对应数据库实体类</typeparam>
        /// <param name="entity">实体对象</param>
        /// <returns>插入SQL</returns>
        public static string CreateInsertSQL<TEntity>(this TEntity[] entity) where TEntity : class,new()
        {
            StringBuilder sql = new StringBuilder(CreateInsertHeaderString<TEntity>());
            foreach (var item in entity)
            {
                sql.Append(CreateValueString(item));
                sql.Append(",");
            }
            return sql.ToString().TrimEnd(',');
        }

        /// <summary>
        /// 创建数据表列字符串
        /// </summary>
        /// <typeparam name="TEntity">实体类类型</typeparam>
        /// <returns>数据表列字符串</returns>
        public static string CreateColumnString<TEntity>() where TEntity : class,new()
        {
            StringBuilder columns = new StringBuilder(" (");
            Type type = typeof(TEntity);
            PropertyInfo[] properties = type.GetProperties();
            foreach (var column in properties)
            {
                if (column.PropertyType.IsValueType || typeof(string).IsEquivalentTo(column.PropertyType))
                {
                    columns.Append(column.Name);
                    columns.Append(",");
                }
            }
            columns.Append(")");
            columns.Replace(",)", ")");
            return columns.ToString();
        }

        /// <summary>
        /// 创建数据表列字符串
        /// </summary>
        /// <typeparam name="TEntity">实体类类型</typeparam>
        /// <returns>数据表列字符串</returns>
        public static string CreateColumnString<TEntity>(this TEntity entity) where TEntity : class,new()
        {
            StringBuilder columns = new StringBuilder(" (");
            Type type = typeof(TEntity);
            PropertyInfo[] properties = type.GetProperties();
            foreach (var column in properties)
            {
                if (column.PropertyType.IsValueType || typeof(string).IsEquivalentTo(column.PropertyType))
                {
                    columns.Append(column.Name);
                    columns.Append(",");
                }
            }
            columns.Append(")");
            columns.Replace(",)", ")");
            return columns.ToString();
        }

        /// <summary>
        /// 创建数据表列字符串
        /// </summary>
        /// <typeparam name="TEntity">实体类类型</typeparam>
        /// <returns>数据表列字符串</returns>
        public static string CreateInsertHeaderString<TEntity>() where TEntity : class,new()
        {
            Type type = typeof(TEntity);
            StringBuilder sql = new StringBuilder(" INSERT INTO ");
            sql.Append("`");
            sql.Append(type.Name);
            sql.Append("`");
            sql.Append(CreateColumnString<TEntity>());
            sql.Append(" VALUES");
            return sql.ToString();
        }

        /// <summary>
        /// 创建数据值字符串
        /// </summary>
        /// <typeparam name="TEntity">实体类类型</typeparam>
        /// <param name="entity">实体对象</param>
        /// <returns>数据值字符串</returns>
        public static string CreateValueString<TEntity>(this TEntity entity) where TEntity : class,new()
        {
            StringBuilder values = new StringBuilder("(");
            Type type = typeof(TEntity);
            PropertyInfo[] properties = type.GetProperties();

            foreach (var column in properties)
            {
                if (column.PropertyType.IsValueType || typeof(string).IsEquivalentTo(column.PropertyType))
                {
                    var valStr = column.GetValue(entity) ?? string.Empty;
                    values.Append("'");

                    if (column.PropertyType.FullName.Contains("Boolean"))
                    {
                        valStr = valStr.ToString().Equals("false", StringComparison.OrdinalIgnoreCase) ? 0 : 1;
                    }

                    values.Append(valStr);
                    values.Append("'");
                    values.Append(",");
                }
            }
            values.Append(")");
            values.Replace(",)", ")");
            return values.ToString();
        }

        /// <summary>
        /// 创建插入到数据库的完整字符串
        /// </summary>
        /// <typeparam name="TEntity">数据库实体类类型</typeparam>
        /// <param name="entity">实体类对象</param>
        /// <returns>插入字符串</returns>
        public static string Insert<TEntity>(this TEntity entity) where TEntity : class,new()
        {
            Type type = typeof(TEntity);
            PropertyInfo[] properties = type.GetProperties().Where(o => o.PropertyType.IsValueType || typeof(string).IsEquivalentTo(o.PropertyType)).ToArray();
            StringBuilder sql = new StringBuilder(" INSERT INTO ");
            sql.Append("`");
            sql.Append(type.Name);
            sql.Append("`");
            sql.Append(" (");
            sql.Append(string.Join(",", properties.Select(o => o.Name)));
            sql.Append(")");
            sql.Append(" VALUES(");
            sql.Append(string.Join(",", properties.Select(o => string.Format("'{0}'", o.GetValue(entity) ?? string.Empty))));
            sql.Append(")");
            return sql.ToString();
        }
    }
}
